package com.site.util.base.dao;

/**
 * Product:BaseLayer
 * Version:1.0
 * Copyright 2009 by DNE
 * All Rights Reserved.
 */

import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.annotation.Resource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.site.util.DateUtils;
import com.site.util.StringUtils;
import com.site.util.base.po.BaseApplicationInfo;
import com.site.util.constant.Constants;
import com.site.util.exception.SystemException;
import com.site.util.extremetable.OrderByUtil;
import com.site.util.extremetable.QueryPage;

/**
 * Dao的基类,提供若干便捷查询方法
 * 所有DAO实现类都必需继承此类。
 */
public class BaseDaoImpl implements BaseDao {
	
	protected Log log = LogFactory.getLog(this.getClass());
	
	private SessionFactory sessionFactory;
	
	@Override
	public <T> void delete(Class<T> clazz, Long id) {
		T entity = getEntityById(clazz, id);
		if(null != entity){
			getSession().delete(entity);
		} else {
			throw new SystemException("SYS_MSG_00016");
		}
	}
	
	@Override
	public <T> List<T> findByClass(Class<T> entity){
		return (List<T>)getSession().createQuery("from " + entity.getName());
	}
	
	@Override
	public <T> List<T> findByHQL(QueryPage queryPage, String hql, Map<String, Object> values, Boolean mark) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		String countQueryString = " select count( * ) " + removeSelect(removeOrders(hql));
		List<T> countlist;
		Query query = getSession().createQuery(countQueryString);
		// 对不变数据进行性能优化
		if(!mark || queryPage.getRecordCount()==0){
			// 是否有参数
			if (values == null) {
				countlist = query.list();
			} else {
				setQueryParams(query, values);
				countlist = query.list();
			}
			// 有多少条记录数据
			if (null == countlist || countlist.size() == 0 || countlist.get(0) == null) {
				recordCount = 0;
			} else {
				recordCount = Integer.parseInt(countlist.get(0).toString());
			}
		} else {
			recordCount=queryPage.getRecordCount();
		}
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			hql = OrderByUtil.sortSql(hql, queryPage.getSortMap());
		}
		query = getSession().createQuery(hql);
		if (values != null) {
			setQueryParams(query, values);
		}
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	
	@Override
	public <T> List<T> findByHQL(QueryPage queryPage, String hql, String asName) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}
		
		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage <= 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		if(StringUtils.isEmpty(asName)) {
			asName = " select count(*) ";
		} else {
			asName = "select count(distinct "+asName+")";
		}
		String countQueryString = asName + removeSelect(removeOrders(hql));
		List<T> countlist = getSession().createQuery(countQueryString).list();

		if (countlist.size() == 0 || countlist.get(0) == null) {
			recordCount = 0;
		} else {
			recordCount = Integer.parseInt(countlist.get(0).toString());
		}

		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			hql = OrderByUtil.sortSql(hql, queryPage.getSortMap());
		}
		Query query = getSession().createQuery(hql);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	@Override
	public <T> List<T> findByHQL(String hql, Map<String, Object> values) {
		
		Query query = getSession().createQuery(hql);
		setQueryParams(query, values);
		List<T> object = query.list();
		if(null != object && object.size() > 0){
			return object;
		}
		return null;
	}
	
	@Override
	public <T> List<T> findByHQLNotRemoveOrderBy(QueryPage queryPage, String hql) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage <= 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		String countQueryString = " select count(*) "
				+ removeSelect(hql);
		List<T> countlist = getSession().createQuery(countQueryString).list();

		if (countlist.size() == 0 || countlist.get(0) == null) {
			recordCount = 0;
		} else {
			recordCount = Integer.parseInt(countlist.get(0).toString());
		}

		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			hql = OrderByUtil.sortSql(hql, queryPage.getSortMap());
		}
		Query query = getSession().createQuery(hql);
		return query.setFirstResult(startIndex).setMaxResults( pageSize).list();
	}
	@Override
	public List<Object[]>  findBySQL(QueryPage queryPage, String sql) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		//如果recordcount已经存在，避免重复查询
		if(queryPage.getRecordCount()==0) {
			String countQueryString = " select count(*) "+ removeSelect(removeOrders(sql));
			recordCount = getCountBySQL(countQueryString);
			queryPage.setRecordCount(recordCount);
		} else {
			recordCount=queryPage.getRecordCount();
		}
		
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}
		Query query = getSession().createSQLQuery(sql);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	
	@Override
	public List<Object[]> findBySQL(QueryPage queryPage,String sql,final Map<String, Object> values) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		final String countQueryString = " select count(*) " + removeSelect(removeOrders(sql));
		List countlist;
		 
		Query query = getSession().createSQLQuery(countQueryString);
		if (values == null) {
			countlist=query.list();
		} else {
			setQueryParams(query, values);
			countlist=query.list();
		}

		if (countlist.size() == 0 || countlist.get(0) == null) {
			recordCount = 0;
		} else {
			recordCount = Integer.parseInt(countlist.get(0).toString());
		}
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}

		query = getSession().createSQLQuery(sql);
		setQueryParams(query, values);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	@Override
	public List<Object[]> findBySQL(QueryPage queryPage,String sql,final Map<String, Object> values,Boolean mark) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		//如果recordcount已经存在，避免重复查询
		if(!mark || queryPage.getRecordCount()==0) {
			String countQueryString = " select count(*) "+ removeSelect(removeOrders(sql));
			recordCount = getCountBySQL(countQueryString);
			queryPage.setRecordCount(recordCount);
		} else {
			recordCount=queryPage.getRecordCount();
		} 
		
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}

		Query query = getSession().createSQLQuery(sql);
		setQueryParams(query, values);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	
	@Override
	public List<Object[]> findBySQL(QueryPage queryPage,String sql,final Map<String, Object> values, String asName) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		if(StringUtils.isEmpty(asName)) {
			asName = " select count(*) ";
		} else {
			asName = "select count(distinct "+asName+")";
		}
		final String countQueryString = asName + removeSelect(removeOrders(sql));
		
		List countlist;
		Query query = getSession().createSQLQuery(countQueryString);
		if (values == null) {
			countlist=query.list();
		} else {
			setQueryParams(query, values);
			countlist=query.list();
		}

		if (countlist.size() == 0 || countlist.get(0) == null) {
			recordCount = 0;
		} else {
			recordCount = Integer.parseInt(countlist.get(0).toString());
		}
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}

		query = getSession().createSQLQuery(sql);
		setQueryParams(query, values);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	} 

	@Override
	public List<Object> findBySQL(QueryPage queryPage, String sql , String asName) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}
		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		if(StringUtils.isEmpty(asName)) {
			asName = " select count(*) ";
		} else {
			asName = "select count(distinct "+asName+")";
		}
		
		String countQueryString = asName + removeSelect(removeOrders(sql));
		
		int count=getCountBySQL(countQueryString);
		if (count==0) {
			recordCount = 0;
		} else {
			recordCount = count;
		}
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}
		Query query = getSession().createSQLQuery(sql);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	
	@Override
	public List<Object[]> findBySQL(final String sql) {
		return getSession().createSQLQuery(sql).list();
	}
	
	@Override
	public List<Object[]> findBySQL(final String sql,final Map<String, Object> params) {
		SQLQuery query=getSession().createSQLQuery(sql);
		setQueryParams(query, params);
		return query.list();
	}
	
	@Override
	public List<Object[]> findBySQLNotRemoveOrderBy(QueryPage queryPage, String sql) {
		int pageSize = queryPage.getPageSize();// 每页记录数
		if (pageSize <= 0) {
			pageSize = QueryPage.DEFAULT_PAGE_SIZE;
		}

		int targetPage = queryPage.getTargetPage();// 当前页
		if (targetPage == 0)
			targetPage = 1;
		int pageCount = 0;// 总页数
		int recordCount = 0;// 总记录数
		
		final String countQueryString = " select count(*) "	+ removeSelect(sql);
		
		int count=getCountBySQL(countQueryString);
		if (count==0) {
			recordCount = 0;
		} else {
			recordCount = count;
		}
		queryPage.setRecordCount(recordCount);
		pageCount = recordCount / pageSize;
		if (recordCount % pageSize > 0)
			pageCount++;
		queryPage.setPageCount(pageCount);
		if(targetPage>pageCount&&pageCount>0){
			targetPage=pageCount;
		}
		// 3. 实际查询返回分页对象
		int startIndex = (targetPage - 1) * pageSize;

		// 处理排序
		if (queryPage.isSorted()) {
			sql = OrderByUtil.sortSql(sql, queryPage.getSortMap());
		}
		Query query = getSession().createSQLQuery(sql);
		return query.setFirstResult(startIndex).setMaxResults(pageSize).list();
	}
	
	@Override
	public <T> List<T> findIntoPOBySQL(String sql,Class<T> clazz) {
		SQLQuery query = getSession().createSQLQuery(sql);  
		return query.addEntity(clazz).list();
	}
	
	@Override
	public int getCountByHQL(final String hql){
		return (Integer)getSession().createQuery(hql).uniqueResult();
	}
	
	@Override
	public int getCountBySQL(final String sql){
		Object object = getSession().createSQLQuery(sql).uniqueResult();
		if(null != object && !object.toString().equals("0")){
			return (Integer)object;
		} else {
			return 0;
		}
	}
	
	@Override
	public Integer executeBySQL(String sql) {
		return getSession().createSQLQuery(sql).executeUpdate();
	}
	
	@Override
	public int getCountBySQL(String sql, Map<String, Object> values) {
		SQLQuery query=getSession().createSQLQuery(sql);
		setQueryParams(query, values);
		return query.executeUpdate();
	}
	
	// 暂时不用纯种池的方式	
//	private static Configuration cfg;
//	private static SessionFactory sessionFactory;
//	/* 实例化线程池 */
//	private ThreadLocal<Session> thread = new ThreadLocal<Session>();
//
//	static {
////		init();
//	}
//	/* 
//	 * 单例模式 
//	 * */
//	private static synchronized void init() {
//		try {
//			if (null == cfg || null == sessionFactory) {
//				cfg = new Configuration().configure();
//				ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(cfg.getProperties()).build();
//				sessionFactory = cfg.buildSessionFactory(serviceRegistry);
//			}
//		} catch (HibernateException e) {
//			e.printStackTrace();
//		}
//	}
//
//	/*
//	 * open方法
//	 * */
//	private void open() {
//		/* 先从线程池中取 */
//		Session session = thread.get();
//		/* 取不到，利用工厂新建 */
//		if (null == session) {
//			session = sessionFactory.openSession();
//			/* 将新建的session放入线程池 */
//			thread.set(session);
//		}
//	}
//	/* 
//	 * close方法
//	 *  */
//	private void close() {
//		try {
//			/* 从线程池中取 */
//			Session session = thread.get();
//			/* 取到，关闭 */
//			if (null != session) {
//				session.close();
//				/* 清空线程池 */
//				thread.set(null);
//			}
//		} catch (HibernateException e) {
//			e.printStackTrace();
//		}
//	}
// 
//	
	@Override
	public <T> T getEntityById(Class<T> clazz,Serializable entityId){
		T entity = (T)getSession().get(clazz, entityId);
		if(null == entity){
			return null;
		}
		return entity;
	}
	
	@Override
	public String getFunc(String funcName) {
        String result = null;
        String sql = "select " + funcName;
        SQLQuery query = getSession().createSQLQuery(sql);
        result = String.valueOf(query.uniqueResult());
        getSession().close();
        return result;
    }
	
	@Override
	public BaseApplicationInfo getNotMarkDeleteEntityById(Class<BaseApplicationInfo> clazz,Serializable entityId) {
		BaseApplicationInfo entity = getEntityById(clazz, entityId);
		if (entity == null) {
			return null;
		}
		if(Constants.MARK_DELETE_YES.equalsIgnoreCase(entity.getMarkDelete())){
			return null;
		}
		return entity;
	}
	
	/**
	 * 获得当前Session
	 * @return
	 */
	public Session getSession() {
		return this.sessionFactory.getCurrentSession();
	}
	
	@Override
	public void markAsDeleted(BaseApplicationInfo clazz,Serializable entityId){
		
		BaseApplicationInfo entity=getEntityById(clazz.getClass(), entityId);
		if(entity==null){
			throw new SystemException("SYS_MSG_00016");
		}
		entity.setModifiedDate(new Date());
		entity.setMarkDelete(Constants.MARK_DELETE_YES);
		getSession().update(entity);
	}
	@Override
	public void markAsEnable(BaseApplicationInfo clazz,Serializable entityId) {
		BaseApplicationInfo entity=getEntityById(clazz.getClass(), entityId);
		if(entity==null){
			throw new SystemException("SYS_MSG_00016");
		}
		entity.setModifiedDate(new Date());
		entity.setMarkDelete(Constants.MARK_DELETE_NO);
		this.getSession().update(entity);
	}
	@Override
	public String oracleToDate(Date date) {
		String text="to_date('"+DateUtils.formatDate(date, "yyyy-MM-dd HH:mm:ss")+"','yyyy-MM-dd hh24:mi:ss')";
		return text;
	}	
	
	@Override
	public String oracleToDate(String datestr) {
		String text="to_date('"+datestr+"','yyyy-MM-dd hh24:mi:ss')";
		return text;
	}
	/**
	 * 去掉HQL语句后面的ORDER BY
	 * @param hql
	 * @return
	 */
	private String removeOrders(String hql) {
		Pattern p = Pattern.compile("order\\s*by[\\w|\\W|\\s|\\S]*",Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(hql);
		StringBuffer sb = new StringBuffer();
		while (m.find()) {
			m.appendReplacement(sb, "");
		}
		m.appendTail(sb);
		return sb.toString();
	}	
	/**
	 * 去掉HQL语句前面的select
	 * @param hql
	 * @return
	 */
	private String removeSelect(String hql) {
		int beginPos = hql.toLowerCase().indexOf("from");
		return hql.substring(beginPos);
	}
	@Override
	public void save(BaseApplicationInfo entity) {
		// 默认修改，创建，为当前时间
		// 删除标记为“N”
		if(entity.getModifiedDate()==null)
			entity.setModifiedDate(new Date());
		if(entity.getCreatedDate()==null)
			entity.setCreatedDate(new Date());
		if (StringUtils.isEmpty(entity.getMarkDelete())) {
			entity.setMarkDelete(Constants.MARK_DELETE_NO);
		}
		getSession().save(entity);
	}
	@Override
	public void save(Object entity) {
		getSession().save(entity);
	}
	/**
	 * 设置参数
	 * @param query
	 * @param params
	 */
	private void setQueryParams(Query query, Map<String,Object> params) {
		if (params != null && params.size() > 0) {
			for (Iterator<Entry<String,Object>> iter = params.entrySet().iterator();iter.hasNext();) {
				Entry<String,Object> entry = iter.next();
				query.setParameter(entry.getKey(), entry.getValue());
			}
		}
	}
	/**
	 * 注入 sessionFactory
	 * @param sessionFactory
	 */
	@Resource
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	@Override
	public void update(BaseApplicationInfo entity) {
		entity.setModifiedDate(new Date());
		getSession().update(entity);
	}
	@Override
	public void update(Object entity) {
		getSession().update(entity);
	}

	@Override
	public <T> String getMaxId(String prefix, Integer count, Class<T> cls) {
		String name = null;
		if(!StringUtils.isEmpty(prefix) && count > 0 && cls != null){
			String hql ="select max(m.id) from "+cls.getName()+" m";
			List<Object> results = this.findByHQL(hql,null);
			Long maxId = 0l;
			if (results != null && results.size() > 0) {
				if(null != results.get(0)){
					maxId = (Long)results.get(0);
				}
			}
			if (maxId == null || maxId == 0l) {
				maxId = 0l;
			}
			name = prefix + String.format("%0"+count+"d", maxId + 1);
		}
		return name;
	}
}